home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-04-25 | 88.4 KB | 3,245 lines |
- Newsgroups: comp.sources.unix
- From: voodoo@hitl.washington.edu (Geoffery Coco)
- Subject: v26i197: veos-2.0 - The Virtual Environment Operating Shell, V2.0, Part14/16
- Sender: unix-sources-moderator@vix.com
- Approved: paul@vix.com
-
- Submitted-By: voodoo@hitl.washington.edu (Geoffery Coco)
- Posting-Number: Volume 26, Issue 197
- Archive-Name: veos-2.0/part14
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 14 (of 16)."
- # Contents: docs/VEOS_The_Complete_Documentation
- # src/kernel_current/shell/xv_glutils.c
- # Wrapped by vixie@efficacy.home.vix.com on Sun Apr 25 23:10:46 1993
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'docs/VEOS_The_Complete_Documentation' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'docs/VEOS_The_Complete_Documentation'\"
- else
- echo shar: Extracting \"'docs/VEOS_The_Complete_Documentation'\" \(41783 characters\)
- sed "s/^X//" >'docs/VEOS_The_Complete_Documentation' <<'END_OF_FILE'
- X
- X
- X
- X
- X
- X
- X
- X*******************************************************************************
- X
- X
- X
- X The VEOS project
- X Human Interface Technology Lab
- X University of Washington
- X Seattle, WA
- X
- X
- X
- X VEOS 2.0
- X
- X Tool Builders Manual
- X
- X
- X
- X
- X Geoffrey P. Coco
- X May 4, 1992
- X
- X
- X
- X
- X
- X*******************************************************************************
- X
- X
- X
- X
- X
- X
- X
- X
- X*******************************************************************************
- X
- X
- X
- X
- X
- X The VEOS Project Team:
- X
- X
- X William Bricken
- X Geoff Coco
- X Dav Lion
- X Andy MacDonald
- X
- X
- X
- X
- X
- X
- X
- X*******************************************************************************
- X
- X
- X
- X
- X
- X
- X*******************************************************************************
- X
- X
- X CONTENTS:
- X
- X
- X* VEOS License Agreement
- X
- X
- X* What is VEOS
- X
- X
- X* Fundamentals of VEOS
- X - Entities
- X - The Grouple
- X - Grouplespaces
- X - Pattern Matching
- X
- X
- X* Components of the VEOS Kernel
- X - Nancy
- X - Talk
- X - Shell
- X
- X
- X* Using VEOS from Lisp
- X - Design Methodology Restated
- X - VEOS Lisp Interface
- X - Nancy Pattern Matching Language
- X - How to Use the Kernel from Lisp
- X
- X
- X* Writing Software Tools in C
- X - Philosophy (please read this section)
- X - Building a Custom Entity with Lisp Interface
- X
- X
- X*******************************************************************************
- X
- X
- X
- X
- X
- X*******************************************************************************
- X*
- X*
- X* VEOS 2.0 Copyright (C) 1992 Geoffrey P. Coco,
- X* Human Interface Technology Laboratory
- X*
- X*
- X* Permission to use, copy, or modify these programs and their documentation
- X* without fee for educational and research purposes only is hereby granted,
- X* provided that this copyright notice appears on all copies and supporting
- X* documentation. For any other uses of this software, in original or modified
- X* form, including but not limited to distribution in whole or in part, specific
- X* prior permission must be obtained from HITL. These programs shall not be
- X* used, rewritten, or adapted as the basis of a commercial software or hardware
- X* product without first obtaining appropriate licenses from HITL. HITL makes no
- X* representations about the suitability of this software for any purpose. It is
- X* provided "as is" without express or implied warranty.
- X*
- X* HITL AND GEOFFREY COCO DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- X* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT
- X* SHALL HITL NOR GEOFFREY COCO BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- X* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- X* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- X* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
- X* OF THIS SOFTWARE.
- X*
- X*
- X* Questions about this software should be addressed to:
- X*
- X* Software Support
- X* Human Interface Technology Laboratory
- X* FJ-15, University of Washington
- X* Seattle, Washington 98195 USA
- X*
- X* or via email:
- X*
- X* veos-support@hitl.washington.edu
- X*
- X*******************************************************************************
- X
- X*******************************************************************************
- X
- X What is VEOS?
- X
- X*******************************************************************************
- X
- X
- XVEOS is an extendable environment for prototyping distributed applications for
- Xunix. The VEOS application programmer's interface is provided by XLISP 2.1 (by
- XDavid Betz). XLISP provides familiar program control; VEOS provides
- Xinterprocess message passing and content addressable database access.
- X
- XVEOS (The Virtual Environment Operating Shell) was developed for distributed
- XVirtual Reality applications at The Human Interface Technology Lab in Seattle
- Xand has been in use for two years. However, VEOS is by no means limited to
- Xthese types of applications.
- X
- XVEOS is ideal for applications where hardware resources are not physically
- Xproximal or where machine-dependent resources (e.g. software packages, interface
- Xdevices, etc..) are isolated because of their platform.
- X
- XVEOS is also ideal for prototyping programs which employ coarse grain
- Xparallellism. That is, VEOS uses heavyweight sequential processes,
- Xcorresponding roughly to unix processes. In this way, VEOS can be used to
- Xutilize a network of workstations as a virtual multiprocessor.
- X
- XC programmers can build custom VEOS tools which are accessable from XLISP and
- Xthus are immediately compatible with other VEOS tools. Lisp programmers can
- Xquickly design and run distributed programs utilizing diverse hardware and
- Xsoftware resources.
- X
- XVEOS is not an operating system. VEOS is a user-level framework for prototyping
- Xdistributed applications. Its primary focus is flexibility and ease of use.
- XThis design comes somewhat at the expense of real-time performance. This is not
- Xto say, however, that VEOS cannot achieve good performance with proper
- Xapplication structuring and tuning.
- X
- XRelying on only the most common unix interface, VEOS is platform independent.
- XVEOS 2.0 has been extensively tested on platforms such as DEC 5000, Sun 4, and
- XSilicon Graphics VGX and Indigo.
- X
- XVEOS, the Virtual Environment Operating Shell, is a software environment for
- Xprototyping distributed virtual world applications.
- X
- X*******************************************************************************
- X
- X*******************************************************************************
- X
- X Fundamentals of VEOS
- X
- X*******************************************************************************
- X
- X
- XWith VEOS, a programmer can specify how to accomplish the many computational
- Xtasks of a proposed virtual environment. VEOS allows a programmer to clump
- Xthese tasks into computational nodes of a distributed system. These clumps of
- Xcomputational tasks are known as 'entities'.
- X
- XPresently in VEOS, each entity is implemented as a distinct Unix process with
- Xthe following native capabilities: interpretation of a coded task description
- X(presently written in lisp), inter-entity communication, generalized data
- Xmanagement (akin to tuple architecture), and generic pattern matching over local
- Xdata space.
- X
- XWith VEOS, a designer can implement a virtual environment using a set of
- Xentities, each residing on the same or different Unix based machines (presumimg
- Xnetwork accessibility). Furthermore, because VEOS relies only on the most
- Xcommon Unix interface, one virtual environment application may utilize multiple
- Xhardware platforms.
- X
- XThe best method for utilizing VEOS entities as nodes in a distributed
- Xapplication greatly depends on the parameters of the applcation (e.g. the
- Xcomputational resources available, the topology of the network, the location and
- Xcompatibility of interface devices, etc..). Consequently, the VEOS design,
- Xwhereever possible, foregoes making policy decisions so that the programmer
- Xenjoys maximum flexibility in designing a distributed application.
- X
- XVEOS programmers have had mixed results with various distributed models (e.g.
- XThe Fern System). It should prove useful to study these prototypical models for
- Xsubtleties before attempting a full-scale distributed application with VEOS.
- X
- X
- X
- X Entities
- X ...
- X
- X
- XSince VEOS is intended as a software platform for distributed virtual
- Xenvironment applications, a primary design focus was the mechanism for
- Xspecifying the tasks and assigning computational resources in a distributed
- Xdesign. The resulting model is the following.
- X
- XA VEOS application is broken down into distinct processes which are as
- Xself-reliant as possible (the more self-reliant, the more efficient the whole
- Xsystem will be). Each process can be coded separately with provisions for
- Xcommunicating with the other processes in the system. Each process is
- Ximplemented by a single VEOS entity on any network accessible Unix workstation.
- X
- XA VEOS entity, then, is a stand-alone executable program that is equipped with
- Xthe same VEOS native capabilities: data management, process management, and
- Xinter-entity communication.
- X
- X
- X The Grouple
- X ...
- X
- XOne of VEOS's aims is to support a consistent and general format for program
- Xspecification, inter-entity communication and database management.
- X
- X
- XIndependently, these needs can be solved by some existing methods. For example,
- XLisp provides generalized data abstraction (i.e. lists), and useful program
- Xcontrol. Mathematica provides a generalized specification format and consistent
- Xtreatment of data and function. Linda provides generalized data management.
- X
- X
- XBut these tools do not share a common form. In addition, large components of
- Xthese systems are extraneous for most situations. Thus, intergrating such
- Xpackages would prove costly and wasteful. Moreover, tying together such varied
- Xsystems emphasizes the differences between their respective forms and
- Xexpressions rather than their commonalities.
- X
- XConsequently, we chose an enhancement to the tuple as the VEOS general format.
- XThis format is called the 'grouple'. Grouples can be seen as a nestable tuples.
- XGrouples are extrordinarily general for flexibility, yet the data they contain
- Xcan be accessed specifically for debugging and performance efficiency. The
- Xsubfields of a grouple are called 'elements'. As grouples can be nested, an
- Xelement can be a grouple.
- X
- XNancy, the VEOS data manager uses the grouple for it's standard data format.
- XTalk, the VEOS communications module, transports linearized grouple stuctures.
- X
- XVEOS now has a lisp interface. The Lisp language was chosen because there is a
- Xclear mapping from lisp lists to VEOS grouples. Furthermore, because lisp
- Xboasts program-data equivalence, programmers can store and pass fragments of
- Xentity specification using the VEOS kernel mechanisms.
- X
- X
- X Grouplespaces
- X ...
- X
- XTechnically, a grouplespace is an ordinary grouple. There are two grouplespaces
- Xassociated with an entity which partition the entity's data according to the
- Xfollowing semantics.
- X
- XThe grouplespaces are: the workspace, the programmer's runtime database. And
- Xthe inspace, where incoming inter-entity messages are placed. In VEOS 2.0, the
- Xinspace has been bypassed as an efficiency concern.
- X
- X
- X Pattern Matching
- X ...
- X
- XThe regime of pure algebraic reduction is well known to provide the ability to
- Xperform many kinds of computation (see prolog). This scheme, also known as the
- XMatch/Substitute/Execute paradigm (ex. in expert systems) can be implemented
- Xusing a pattern matching mechanism.
- X
- XNancy supports pattern matching over its grouplespaces. A pattern is a specific
- Xform that data can take. Patterns can contain specific data to match or
- Xwildcard symbols which can be used to bind variables to values. For specifics
- Xof the Nancy Pattern Matching Language, see the section Using VEOS from Lisp.
- X
- X
- X
- X*******************************************************************************
- X
- X Components of the VEOS Kernel
- X
- X*******************************************************************************
- X
- X
- X Nancy: The VEOS grouple manager
- X ...
- X
- XNancy is a homebrew database manager designed specifically for the VEOS project.
- XMuch like Linda systems manage data as tuples, Nancy mananges data as grouples.
- X
- XNancy performs all grouple manipulation within VEOS. This involves creation,
- Xdestruction, insertion, copying, etc.. Since Nancy grouplespaces are merely
- Xnamed grouples, these are also an entity's fundamental database operations.
- X
- XIn addition, Nancy provides a powerful semantic for data searching, inserting
- Xand replaceing within a grouplespace. This is the pattern matcher. It is a
- Xcomplete set of primitives to implement a match/substitute/execute engine as in
- Xan expert system.
- X
- XFrom lisp, programmers have access to three Nancy operations, vput, vcopy and
- Xvget. These are sufficient for all grouplespace operations. As lisp
- Xexpressions are passed to these nancy primitives, they are converted to grouple
- Xformat and then handled by nancy's standard C interface.
- X
- X
- X
- X Talk: The VEOS communications module
- X ...
- X
- XTalk is the only supported mechanism for entity communication. As VEOS entities
- Xprovide coarse grain parallelism though Unix processes, process (entity)
- Xsynchronization and shared memory is not practical. Thus VEOS supports message
- Xpassing as the only means of entity communication.
- X
- XTalk provides VEOS with two simple message passing primitives, vthrow and
- Xvcatch. From lisp, programmers can transmit a message *asynchronously* to
- Xanother entity. The receiving entity is then at leisure to receive the message,
- Xalso *asynchronously*.
- X
- XAsynchronous message passing means this: When an entity tranmits a message, the
- Xoperation succeeds *reliably*, whether the receiver is waiting for a message or
- Xnot. Likewise, an entity can always check for incoming messages without waiting
- Xindefinitely for a message to arrive. This is also called non-blocking
- Xcommunication.
- X
- XTalk passes messages between entities with a flat linearized grouple format.
- XThe lisp/veos interface module performs this translation.
- X
- X
- X
- X Shell: The VEOS kernel control module
- X ...
- X
- XThe shell is the administrative workings of the VEOS kernel. It dispatches
- Xinitializations, interrupt handling, manages kernel memory, etc..
- X
- X
- X*******************************************************************************
- X
- X Using VEOS from LISP
- X
- X*******************************************************************************
- X
- X
- X ----------------
- X veos methodology
- X----------------
- X
- X
- Xthe veos kernel provides:
- X
- X 1. fast and powerful local database access.
- X - built-in pattern matching.
- X - internal grouple form converts to lisp lists.
- X
- X 2. clean and reliable message passing.
- X - utilizes Berkeley sockets.
- X - symbolic entity addressing.
- X
- X 3. well defined C interface.
- X - can be retrofit to any high-level language (like lisp).
- X
- X
- X
- X ---------------------
- X getting your feet wet
- X---------------------
- X
- X
- X* Get an account on a Unix machine that supports VEOS (Suns, DECs, SGs).
- X
- X* Make sure /home/veos/bin/ is in your path.
- X
- X* You are ready to run a basic VEOS entity. The basic VEOS entity with is built
- X with an xlisp interface. What you get is complete xlisp plus the VEOS native
- X primitives described in the next section.
- X
- X You can run entities at least two ways:
- X
- X 1. Type 'entity' at the Unix command line.
- X
- X 2. Alternatively (and recommended), you can run entities from inside emacs.
- X
- X Within emacs, do meta-x eval-expression:
- X (setq inferior-lisp-program "/home/veos/bin/entity")
- X or put this line in your .emacs file.
- X
- X Then, do meta-x run-lisp. Once in this emacs mode, you can do meta-x
- X describe-mode to learn about fancy emacs features with respect to lisp
- X interaction.
- X
- X* To load a program into lisp, type (load "filename.lsp") to lisp.
- X
- X
- X
- X ---------------------
- X veos kernel interface
- X---------------------
- X
- X Currently xlisp provides the abstract access to veos kernel capabilities. The
- X following describes the native priitives as of February 8, 1992.
- X
- X
- X startup veos kernel from lisp
- X '''''''''''''''''''''''''''''
- X (vinit <port number> )
- X ; initialize veos kernel,
- X ; establish network port for incoming messages.
- X ; if port number is not given, veos chooses an available port.
- X ; vinit returns uid of this entity upon success
- X
- X
- X takedown veos kernel from lisp
- X ''''''''''''''''''''''''''''''
- X (vclose)
- X ; takedown veos kernel,
- X ; cleanup network connections.
- X ; xlisp (exit) function will also perform necessary veos takedown.
- X
- X
- X kernel system tasking
- X '''''''''''''''''''''
- X (vtask)
- X ; pass control to veos kernel to perform network activity.
- X ; for best performance, call vtask every time through
- X ; the entity's main loop, calling (vcatch) immediately
- X ; afterward.
- X
- X
- X local grouplespace access
- X '''''''''''''''''''''''''
- X (vput <data element> <nancy pattern> :freq <"all"> )
- X ; add data to local grouplespace.
- X ; data element can be a list.
- X ; pattern for vput may contain ^.
- X ; optional frequency key-argument ("all" is only value allowed)
- X ; requests exaustive matching.
- X
- X (vcopy <nancy pattern> :test-time <time-stamp> :freq <"all"> )
- X ; non-destructive local grouplespace query.
- X ; pattern for vcopy may not contain ^.
- X ; optional timestamp key-argument must be created by (vmintime)
- X ; given timestamp is modified in place.
- X
- X (vget <nancy pattern> :freq <"all"> )
- X ; destructive local grouplespace query.
- X ; pattern for vget may not contain ^.
- X
- X (vmintime)
- X ; returns a guaranteed oldest time stamp.
- X
- X ; see below for nancy pattern language specification.
- X
- X
- X message passing
- X '''''''''''''''
- X (vthrow (destination1 destination2 ...) (lisp expression) )
- X ; send to a list of desinations.
- X ; list may contain zero or one destination, and
- X ; the same destination may appear more than once.
- X ; destination is lisp vector of hostname and port number,
- X ; ex. '#("vorpal" 7800)
- X ; message is appended to each desination's incoming grouplespace.
- X
- X (vcatch <nancy pattern> )
- X ; perform standard nancy pattern match from incoming grouplespace.
- X ; acts like vget in all other ways.
- X ; since new messages are appended, oldest message is at top.
- X ; to simply retrieve oldest message, use: (vcatch '(> @ @@)).
- X
- X ; NOTE: currently, VEOS 2.0 does not support
- X ; the pattern argument for efficiency reasons.
- X ; (vcatch) simply returns the oldest available message.
- X
- X
- X -------------------------
- X caveats of xlisp for veos
- X-------------------------
- X
- XThere are many types of VEOS data elements. The most common and useful element
- Xtypes to programmers are available from lisp. The VEOS types that are supported
- Xby lisp are:
- X
- X VEOS equivalent in Lisp
- X ------ --------------------
- X
- X grouple list - NIL or () is the empty grouple
- X
- X integer integer - use a regular number
- X
- X float float - use a decimal point
- X
- X string string - use "" to make a string
- X
- X
- XLikewise, lisp supports many data element types. There is an equivalent data
- Xelement in VEOS for some of these. The data elements that VEOS supports are
- Xthose listed above and the following:
- X
- X Lisp equivalent in VEOS
- X ------ --------------------
- X
- X symbol * prim type.
- X
- X vector special grouple
- X
- X
- X* A symbol in lisp can be used for a variable, function, or be unbound. When a
- X lisp symbol is passed to VEOS (for grouplespace storage of message passing),
- X VEOS retains the name of the symbol but not the bindings. Lisp normally retains
- X these symbol bindings.
- X
- XAll other lisp data types are unsupported by VEOS. This means that they cannot
- Xbe passed to Nancy for grouplespace storage. And they cannot be used within
- Xinter-entity messages.
- X
- X
- X -------------------------------
- X nancy pattern matching language
- X-------------------------------
- X
- XNancy controls access to the grouplespaces through a pattern matching language.
- XThe goals of the language are to provide a succinct format to express the locale
- Xin the grouplespace you would like to work and what you would like to do there.
- X
- XThere are three fundamental grouplespace operations that Nancy provides:
- X
- X - find some location (specified by pattern), insert data there.
- X - find some data (specified by pattern), retrieve it.
- X - find some data (specified by pattern), retrieve it and replace it with
- X other data.
- X
- X
- X
- XThus, these are the rules of nancy pattern matching:
- X
- XTo find anything (called a site), specify a pattern. Patterns consist of
- Xinformation about where the site is and/or specific data that the site contains.
- X
- X The ^ (void) symbol specifies a location within a grouple for inserting. It
- X points to the void between data. Technically, the ^ always matches.
- X
- X The > (mark) symbol points to a piece of data within a grouple retrieval or
- X replacement operation. It designates the immediately following element of
- X the pattern as the site of action. The > does not itself match data.
- X
- X
- XFor a pattern to be meaningful, one of these symbols (^ or >) must appear
- Xsomewhere in the pattern. In other words, the pattern must always specify a
- Xsite of action.
- X
- XTo match data within a pattern, you can either specify actual data to compare,
- Xor wildcard symbols which are content-blind.
- X
- X The @ (this) symbol specifies a single element at a specific location within
- X a grouple. This will match any single element including a grouple.
- X
- X The @n (these) symbol specifies exactly n sequential elements within a
- X grouple. This will match the next n elements. @1 is equivalent to @.
- X
- X The @@ (these all) symbol specifies zero or more elements within a grouple.
- X This will match all the remaining elements in a grouple. This special form
- X is allowed only at the end of a pattern grouple.
- X
- X The ** (any) symbol specifies zero or more elements *anywhere* within a
- X grouple. This will match all the remaining unmatched elements in a grouple.
- X This special form is allowed only at the end of a pattern grouple.
- X
- X The ~ (touch) symbol specifies that the immediately following element be
- X 'touched' during a (vput ...) operation. That is, the data that matches
- X the pattern symbol following the ~ is marked as having been recently
- X modified. There can be any number of ~ in a pattern.
- X
- X Anything else is taken literally and compared with the actual data in the
- X grouplespace.
- X
- X Note that nancy patterns are recursive. That is, a pattern may
- X contain a grouple which may contain wildcards and data, some of which
- X are more grouples, etc..
- X
- X
- XExamples.
- X
- XHere is an actual session with lisp. My comments are added.
- X
- X;; we begin with an empty grouplespace, ie ().
- X;; to vput, we match the grouplespace and point to the void within it.
- X;; thus, the (^) pattern.
- X;; this is literally where the given data is put.
- X
- X> (vput "first" '(^))
- XT
- X
- X;; here, we reqeusted a simple insert operation. so vput vput return T or NIL
- X;; depending on the success of the match. during a replace vput operation, vput
- X;; returns what your action replaced in the grouplespace. in a moment, we'll
- X;; see when this comes into play.
- X
- X
- X
- X;; to see the entire contents of the grouplespace, we need to do a
- X;; nondestructive query. the most succinct way to do this is to match the
- X;; grouplespace and copy all of its elements:
- X
- X> (vcopy '(> @@))
- X("first")
- X
- X;; note that the @@ can match a single element if there is only one, or it can
- X;; match many elements if there are more than one. in the latter case, the
- X;; results are conveniently returned in a list. in the interest of consistency,
- X;; all nancy results are returned in lists.
- X
- X
- X
- X;; let's now insert a list after the first element of the grouplespace:
- X
- X> (vput '("third") '(@ ^))
- XNIL
- X
- X;; again, no data was removed in the process.
- X
- X
- X
- X;; the entire contents...
- X
- X> (vcopy '(> @@))
- X("first" ("third"))
- X
- X
- X
- X;; let's now insert an element between the first element and all the rest of the
- X;; elements in the grouplespace.
- X
- X> (vput "second" '(@ ^ @@))
- XNIL
- X
- X;; note that (@ ^ @) would have also worked anbd would have been more precise.
- X
- X
- X
- X;; inspect the entire contents
- X
- X> (vcopy '(> @@))
- X("first" "second" ("third"))
- X
- X
- X
- X;; here, we are inserting a vector into the grouplespace.
- X;; this demonstrates two other features. the @2, in the given position in
- X;; the pattern matches the first two elements of the grouplespace. the "third" in
- X;; the pattern matches the actual data in the grouplespace. this, of course, is
- X;; unlike how an @ matches any element where no data is compared.
- X
- X> (vput '#(1.4 3.9 9.0) '(@2 ("third" ^)))
- XNIL
- X
- X
- X
- X;; the data now resides where the ^ was in the previous pattern.
- X
- X> (vcopy '(> @@))
- X("first" "second" ("third" #(1.4 3.9 9)))
- X
- X
- X
- X;; sometimes it is useful to replace existing data in the grouplespace.
- X;; this can be done by removing, then inserting correct data.
- X;; or it can be done with a replacing vput.
- X;; here, we replace the first element of the grouplespace with the given data.
- X;; we must also match the remaining elements in the grouplespace to achieve a
- X;; successful match.
- X
- X> (vput "uno" '(> @ @@))
- X("first")
- X
- X;; vput returns the removed data.
- X
- X
- X
- X;; and the first element has been replaced.
- X
- X> (vcopy '(> @@))
- X("uno" "second" ("third" #(1.4 3.9 9)))
- X
- X
- X
- X;; now, let's look at the more subtle features of pattern matching. begin by
- X;; emptying the current contents of the grouplespace to begin a new session.
- X
- X> (vget '(> @@))
- X("uno" "second" ("third" #(1.4 3.9 9)))
- X
- X
- X;; confirm that the grouplespace is empty
- X
- X> (vcopy '(> @@))
- XNIL
- X
- X
- X;; here, we'll insert some new data
- X
- X> (vput '("animal" "giraffe") '(^))
- XT
- X> (vput '("plant" "fern") '(^ @))
- XT
- X> (vput '("animal" "lion") '(^ @2))
- XT
- X> (vcopy '(> @@))
- X(("animal" "lion") ("plant" "fern") ("animal" "giraffe"))
- X
- X
- X
- X;; now we can perform useful matches on the grouplespace. suppose we want to
- X;; find the tag associated with the "fern" data. we simply ask for the element
- X;; immediately preceding the "fern" element. note the use of the ** wildcard.
- X;; the ** pattern element has two functions in this pattern. first, like @@ it
- X;; matches all the reminaing elements in the grouple. second, it explicitly
- X;; makes the containing grouple an order-independent pattern. in other words,
- X;; when nancy sees a ** in a pattern grouple, it ignores the order of the source
- X;; (grouplespace) elements when matching; it matches purely by content.
- X
- X> (vcopy '((> @ "fern") **))
- X("plant")
- X
- X;; note that although the marked element is "plant", but the result is contained
- X;; within an extra grouple. as explained above, all nancy results are contained
- X;; within a grouple.
- X
- X
- X
- X
- X;; if we want to find the data associated with the tag "animal", we can do a
- X;; similar match.
- X
- X> (vcopy '(("animal" > @) **))
- X("lion")
- X
- X
- X
- X
- X;; but this is only a partial answer. because there is more than one instance
- X;; of the tag "animal" at that level of the grouplespace. we may want all the
- X;; possible matches of this form.
- X
- X> (vcopy '(("animal" > @) **) :freq "all")
- X("lion" "giraffe")
- X
- X
- X;; we can also use this feature with vput to do an exaustive replace. here,
- X;; xlisp allows the arguments to a function to appear on consecutive lines.
- X
- X> (vput "mammal"
- X '((> "animal" @) **)
- X :freq "all")
- X("animal" "animal")
- X
- X;; vput returns exactly what it replaced.
- X;; check that the replace was successful.
- X
- X> (vcopy '(> @@))
- X(("mammal" "lion") ("plant" "fern") ("mammal" "giraffe"))
- X
- X
- Xnow let's look at the pattern matching features that correspond to the
- Xdynamic issues of maintaining the grouplespace. specifically, matching that
- Xis sensitive to the relative ages of the data can be used for so-called
- X'delta matching'. we can use the previous contents to illustrate.
- X
- Xfirst, we'll make a nancy time stamp.
- X
- X> (setq ts (vmintime))
- X0
- X
- X
- X;; we'll use this time stamp with vcopy. if you pass a time stamp to vcopy, it
- X;; perform the given match but only returns matched data that is *younger* than
- X;; the time stamp. vmintime returns a guaranteed oldest time-stamp. this means
- X;; that using it will guarantee seeing everything in the grouplespace.
- X
- X> (vcopy '(> @@) :test-time ts)
- X(("mammal" "lion") ("plant" "fern") ("mammal" "giraffe"))
- X
- X;; vcopy compared all the matched data against the time stamp, all of it had
- X;; been modified (with vput) after the time given by the time stamp.
- X
- X
- X
- X;; vcopy *modifies* your time stamp in place to reflect that you've matched with
- X;; that pattern. and as you can see, the time stamp has now been modified.
- X
- X> ts
- X1.4013e-44
- X
- X
- X
- X;; if we make the same match again with the same time stamp, we see no data.
- X;; this corresponds to there being no change (or delta) in the data since we
- X;; last matched.
- X
- X> (vcopy '(> @@) :test-time ts)
- XNIL
- X
- X
- X
- X;; let's insert some new data to see how the delta will be shown.
- X
- X> (vput '("mammal" "fox") '(> (@ "lion") **))
- X(("mammal" "lion"))
- X
- X
- X
- X;; when we match the entire grouplespace with our time stamp, we only get the
- X;; new data, since it was added since our last match.
- X
- X> (vcopy '(> @@) :test-time ts)
- X(("mammal" "fox"))
- X
- X
- X
- X;; again the time stamp has been modified in place to reflect a new matching.
- X;; here we inspect the time stamp only to show that is has been changed. the
- X;; actual value in the time stamp is irrelevant - it used internally by nancy.
- X
- X> ts
- X1.82169e-44
- X
- X
- X
- Xnotice that above we replaced both the data and the tag ("mammal" "fox") in
- Xthe grouplespace. suppose that we want to replace only the data in the
- Xgrouplespace.
- X
- X> (vput "carrot" '((@ > "fern") **))
- X("fern")
- X
- X> (vcopy '(> @@) :test-time ts)
- X(("carrot"))
- X
- X;; as expected, vcopy returns only the changed data.
- X
- X
- X
- X;; above, the changed data is ambiguous without its tag. but the tab was not
- X;; modified and so is not returned. we can use the 'touch' feature during a
- X;; vput to mark elements in the grouplespace as having also been modified.
- X
- X> (vput "palm" '((~ @ > "carrot") **))
- X("carrot")
- X
- X;; note the ~ pattern modifier. if the pattern successfully matches, nancy
- X;; 'touches' the element following the ~ in the pattern as having been modified.
- X
- X
- X
- X> (vcopy '(> @@) :test-time ts)
- X(("plant" "palm"))
- X
- X;; and this is exactly what we wanted.
- X;; unlike the > or ^ symbols, you can any number of ~ in a vput pattern.
- X
- X
- X
- X;; it is important to remember that a single time stamp represents the most
- X;; recent match of a *particluar* pattern from a *particular* point of view.
- X;; for example, if you're writing program for a server entity to which many
- X;; entities make matching requests, the server should maintain a time stamp for
- X;; each entity and each pattern type. see the fx.lsp file of the Fern System
- X;; for examples of this strategy.
- X
- X
- X ---------------------
- X how to use the kernel
- X---------------------
- X
- X - since all behavior description is specified in lisp, (and thus all
- X kernel primitive composition), lisp's native evaluation mechanism is
- X best suited to direct flow control.
- X
- X - it is an explicit goal of veos to provide program distribution
- X services to generic programming frameworks. that is, the language we
- X supplant above veos must be independent of the kernel
- X implementation. were process control a kernel resposibility, the
- X kernel would require language-specific maintenance and would directly
- X oppose the stated fundamental premise.
- X
- X - the mechanism in lisp for handling entity process management is available.
- X it consists of a main processing loop as described below. each pass
- X through the loop can be thought of as a 'frame'. that is, one complete
- X cycle through all an entity's responsibilities constitutes a quanta
- X of entity activity.
- X
- X
- X 1. invoke kernel maintenance.
- X
- X this entails polling network, garbage collection, etc..
- X
- X
- X 2. gather waiting inter-entity messages.
- X
- X this process can be augmented by filtering. In VEOS 2.0,
- X this filtering feature has been disabled for performance reasons.
- X
- X
- X 3. evaluate messages from (2).
- X
- X implemented with lisp's eval.
- X
- X eval directs program control to the 'program stubs' contained
- X within the messages. thus, messages are single lisp
- X expressions. for example, the message:
- X (add-to-database (frog x1 y1) (bird x2 y2))
- X is a program stub that when evaluated by lisp will invoke the
- X function 'add-to-database' with the arguments (frog x1 y1)
- X and (bird x2 y2).
- X
- X
- X 4. give processing burst to background tasks.
- X
- X remember that each entity is a single unix process. and in general, a
- X process is the smallest grain of parallelism that unix supports.
- X consequently, there is no explicit provision in veos for concurrency
- X (e.g. lightweight threads) *within* an entity.
- X
- X but sometimes it is conceptually easier to design a program with
- X concurrency in mind. this desire for parallelism can be fulfilled
- X with virtual processes.
- X
- X given this regime of processing 'frames', programmers may simulate
- X concurrent processes with discrete background tasks. these tasks can
- X be implemented as functions (program stubs) which perform a frame of
- X computation and quickly return.
- X
- X the process table is a lisp association list of program stubs.
- X program stubs are small fragments of lisp code that can compose an
- X entity's behavior program stubs should never block.
- X
- X - an entity's main processing loop can be expressed in lisp by:
- X
- X (defun go ()
- X (loop
- X (do-frame)))
- X
- X (defun do-frame ()
- X (progn
- X
- X ;; kernel maintenance
- X (vtask)
- X
- X ;; gather and evaluate waiting messages
- X (do ((msg (vcatch)))
- X ((null msg))
- X
- X (eval msg)
- X (setq msg (vcatch))
- X )
- X
- X ;; give processing burst to background processes
- X (dolist (proc background-procs)
- X (eval (cadr proc)))
- X ))
- X
- X
- X - since VEOS is intended as a prototyping system, the design is based
- X less on performance considerations and more on reliable functionality.
- X you will notice that the above scheme ignores many real-time issues.
- X
- X for example, messages may arrive while an the entity is servicing
- X background processes. thus, messages must wait an average of half the
- X time of a processing frame before being evaluated. thus, when an
- X entity is heavily loaded, there may be significant latency in message
- X passing. this can be troublesome when attempting to sychronize
- X entities though message passing.
- X
- X likewise, important work may be waiting in the backgound processes while
- X the entity is servicing messages. this can be troublesome when
- X attempting to ensure reliable interface device update rates.
- X
- X these problems can be lessened through judicious use of inter-entity
- X messages (i.e. as few and small as possible) and through efficient and
- X sparing use of background tasks.
- X
- X
- X - The Fern System is a good example of how to use VEOS from lisp. It
- X is included with the VEOS distribution.
- X
- X*******************************************************************************
- X
- X Writing Software Tools in C
- X
- X*******************************************************************************
- X
- X
- X== Philosophy ==
- X
- XAny software tool can be integrated with VEOS. However, certain features of
- Xsoftware tools make them easier to integrate. The process of VEOSifying a
- Xsoftware tool is writing custom lisp primitives (usually in C) which decode lisp
- Xarguments and pass control to the software tool.
- X
- XGiven that all control will be passed to a tool via lisp primitives, the
- XVEOSified tool will perform best if it is:
- X
- Xnon-blocking:
- X That is, primitives should always return after a reasonable slice of time
- X (depends on application).
- X
- Xinterrupt-driven is ok:
- X As long as primitive entry points appear to accomplish their tasks quickly
- X (use static caches, etc..). In fact, for polling type software tools (input
- X device drivers, etc..), interrupts are preferrable to timeout reads in some
- X situations. Especially when data arrival is infrequent.
- X
- Xmodular:
- X The tool should perform distinct, well-defined tasks. This assists the lisp
- X programmer with task specification. And it makes writing custom primitives
- X easy.
- X
- Xrobust:
- X Eg, can handle lags in data flow, can handle out-of-band data, etc..
- X Remember, world designers will want to rely on these distributed services.
- X
- X
- X
- X
- X== Building a Custom Entity with Lisp Interface ==
- X
- X
- XThe xlisp that is bound with with VEOS is a software library that anybody can
- Xuse. You can compile the xlisp library once, then link in user-defined lisp
- Xprimitives at runtime. Or, you can recompile xlisp by declaring user-defined
- Xprimitives in advance as the xlisp documentation describes. This section only
- Xdescribes the dynamic scheme for binding xlisp primitives.
- X
- XTo use this version of xlisp, you need to provide two functions that xlisp
- Xexpects.
- X
- XThe first function ( xlinclude_hybrid_prims() ) supplies xlisp with the function
- Xpointers of your user-defined primitives (also called hybrid primitives). If
- Xyou're not binding any user-defined primitives (ie. making basic xlisp w/o
- XVEOS), this function should have an empty body. See file
- X/home/xlisp/xexec/c/main.c for an example of the bare-bones main.
- X
- XThe second function ( xlhybrid_shutdown() ) gives user defined modules a chance
- Xto clean their respective environments become xlisp exits. xlisp will call this
- Xfunction just before a graceful exit. Again, if no special actions are to be
- Xtaken, give this function an empty body.
- X
- XLastly to use this version of xlisp, you need to provide a main() function. In
- Xyour main(), do any setup that is required, then call xlisp's main ( xmain() ).
- Xxmain() will never return. Notice that VEOS does not do any setup in main()
- X(see example file below). Instead, kernel setup is a lisp primitive. This
- Xpractice is encouraged since it allows users to decide when to use particular
- Xmodules.
- X
- XWhat follows are the step-by-step instructions to build a VEOS entity with xlisp
- Xand and other custom software tools:
- X
- X1. Create a main control file that minimally looks like this:
- X
- X
- X/***************************************************************************************
- X * Copyright (C) 1992 Human Interface Technology Lab, Seattle *
- X ****************************************************************************************/
- X
- X#include "world.h"
- Xextern xmain();
- X
- X
- X/***************************************************************************************
- X * main
- X * launchpad of any stand-alone program
- X ****************************************************************************************/
- Xmain(argc, argv)
- X int argc;
- X char *argv[];
- X{
- X /** call the xlisp controller, never returns **/
- X xmain(argc, argv);
- X }
- X
- X
- X/***************************************************************************************
- X * xlinclude_hybrid_prims
- X * lisp calls this function to load user-defined lisp primitives
- X ****************************************************************************************/
- Xxlinclude_hybrid_prims()
- X{
- X /** load veos native lisp primitive entries.
- X ** this function lives in the xvnative_glue library
- X **/
- X Shell_LoadNativePrims();
- X
- X
- X /** here, make calls to other software tool setup functions **/
- X MyModule_LoadMyPrims();
- X }
- X
- X
- X
- X/***************************************************************************************
- X * xlshutdown_hybrid
- X * lisp calls this function before graceful exit
- X ****************************************************************************************/
- Xxlshutdown_hybrid()
- X{
- X /** let the kernel unwind
- X ** this function lives in the kernel library
- X **/
- X Kernel_Shutdown();
- X
- X /** here, make calls to other software tools shutdown code **/
- X }
- X
- X
- X2. Create a file that contains your primitives. Write C functions which handle
- X lisp arguments. These functions are the glue between your software and
- X lisp (ie. your primitives). See the kernel interface files, xv_native.c and
- X xv_glutils.c, for model code. You may use any of the utilities found in
- X these files. The functions themselves are compiled into the xvnative_glue
- X library.
- X
- X In this file, provide xlisp with the function pointers to your primitives. In
- X step 1, the function xlinclude_hybrid() loads all the user-defined prims. In
- X addition to loading the native kernel primitives, it should call a function like
- X this to load your primitives into lisp:
- X
- X
- X#include "xlisp.h"
- X
- X/***************************************************************************************
- X * MyModule_LoadMyPrims
- X * load user-defined lisp primitives
- X ***************************************************************************************/
- XTVeosErr MyModule_LoadMyPrims()
- X{
- X DEFINE_SUBR( "ROLLOVER", Tricks1_RollOver )
- X DEFINE_SUBR( "PLAYDEAD", Tricks2_PlayDead )
- X DEFINE_SUBR( "FETCH", Tricks3_Fetch )
- X DEFINE_SUBR( "GONUTS", Tricks4_GoNuts )
- X
- X DEFINE_FSUBR( "REPEAT", Tricks5_Repeat )
- X
- X /** NOTES:
- X **
- X ** No semicolon is necessary after these macros.
- X ** This is to preserve compatibility with another xlisp
- X ** mechanism for including user-defined functions.
- X **
- X ** First arg is name you want prim to be in lisp, use all CAPS.
- X ** Second arg is actual C function, must return an LVAL.
- X ** Use DEFINE_FSUBR for lisp special forms.
- X ** Most likely you wont need them.
- X **/
- X
- X return(VEOS_SUCCESS);
- X }
- X/***************************************************************************************/
- X
- X
- X3. Compile your main and primitives and link with the options:
- X
- X -L/home/veos/lib/
- X -lxlisp -lxvnative_glue -lkernel
- X
- X See VEOS kernel makefile for example build sequence.
- X Don't forget to link to the software packages which contain included primitives.
- X Notice that the kernel and the kernel interface to lisp are separate libraries.
- X
- X
- X4. Now you have a stand-alone entity. This entity should behave just like the
- X base-level entity for application-nonspecific tasks, ie. standard lisp.
- END_OF_FILE
- if test 41783 -ne `wc -c <'docs/VEOS_The_Complete_Documentation'`; then
- echo shar: \"'docs/VEOS_The_Complete_Documentation'\" unpacked with wrong size!
- fi
- # end of 'docs/VEOS_The_Complete_Documentation'
- fi
- if test -f 'src/kernel_current/shell/xv_glutils.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'src/kernel_current/shell/xv_glutils.c'\"
- else
- echo shar: Extracting \"'src/kernel_current/shell/xv_glutils.c'\" \(43094 characters\)
- sed "s/^X//" >'src/kernel_current/shell/xv_glutils.c' <<'END_OF_FILE'
- X/****************************************************************************************
- X * *
- X * file: xv_glutils.c *
- X * *
- X * Sundry utilities which serve as glue for xlisp veos primitives. *
- X * *
- X * creation: April 13, 1992 *
- X * *
- X * *
- X * by Geoffrey P. Coco at the HITLab, Seattle. *
- X * *
- X ****************************************************************************************/
- X
- X
- X/****************************************************************************************
- X * Copyright (C) 1992 Geoffrey P. Coco, Human Interface Technology Lab, Seattle *
- X ****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************
- X * preliminaries */
- X
- X#include <math.h>
- X#include "xlisp.h"
- X
- X/* VEOS definitions: */
- X#include "kernel.h"
- X
- X#define NATIVE_CODE
- X#include "xv_native.h"
- X#undef NATIVE_CODE
- X
- X/****************************************************************************************/
- X
- Xextern LVAL xsendmsg0();
- Xextern LVAL s_unbound;
- Xextern LVAL true;
- Xextern LVAL xlfatal();
- X
- X/****************************************************************************************/
- X
- Xboolean native_bSubstBeenMarked;
- Xboolean native_bVoidBeenMarked;
- Xboolean native_bDestruct;
- X
- X#define SUBST native_bSubstBeenMarked
- X#define VOID native_bVoidBeenMarked
- X#define MOD native_bDestruct
- X
- X/****************************************************************************************/
- X
- XTVeosErr Native_PatVEltClerical();
- Xextern LVAL ReverseList();
- X
- X/****************************************************************************************/
- X
- X
- X
- X
- X/****************************************************************************************
- X Basic Xlisp <--> Nancy Conversion
- X ****************************************************************************************/
- X
- X
- X/****************************************************************************************/
- XTVeosErr Native_XEltToVElt(pXElt, pVElt)
- X LVAL pXElt;
- X TPElt pVElt;
- X{
- X TVeosErr iErr;
- X
- X iErr = VEOS_FAILURE;
- X
- X
- X /** NIL is the empty grouple **/
- X
- X if (null(pXElt)) {
- X iErr = Nancy_NewGrouple(&pVElt->u.pGr);
- X pVElt->iType = GR_grouple;
- X }
- X
- X
- X /** case-wise conversion to nancy format **/
- X
- X else {
- X switch (ntype(pXElt)) {
- X
- X case CONS:
- X /** a list becomes a grouple **/
- X iErr = Native_ListToGrouple(pXElt, &pVElt->u.pGr);
- X pVElt->iType = GR_grouple;
- X break;
- X
- X case VECTOR:
- X /** a vector becomes a special grouple **/
- X iErr = Native_VectToGrouple(pXElt, &pVElt->u.pGr);
- X pVElt->iType = GR_vector;
- X break;
- X
- X case FIXNUM:
- X pVElt->iType = GR_int;
- X pVElt->u.iVal = getfixnum(pXElt);
- X break;
- X
- X case FLONUM:
- X pVElt->iType = GR_float;
- X pVElt->u.fVal = (float) getflonum(pXElt);
- X break;
- X
- X case STRING:
- X pVElt->iType = GR_string;
- X pVElt->u.pS = strdup((char *) getstring(pXElt));
- X break;
- X
- X case SYMBOL:
- X pVElt->iType = GR_prim;
- X pVElt->u.pS = strdup(getstring(getpname(pXElt)));
- X break;
- X
- X default:
- X iErr = NATIVE_BADVTYPE;
- X break;
- X
- X }
- X }
- X
- X return(iErr);
- X
- X } /* Native_XEltToVElt */
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************/
- XTVeosErr Native_ListToGrouple(pList, hGrouple)
- X LVAL pList;
- X THGrouple hGrouple;
- X{
- X TVeosErr iErr;
- X LVAL pXFinger;
- X int iElt;
- X TPGrouple pGrouple;
- X TPElt pVFinger;
- X
- X
- X *hGrouple = nil;
- X
- X iErr = Nancy_NewGrouple(&pGrouple);
- X iElt = 0;
- X
- X /** convert each lisp sub-element **/
- X
- X pXFinger = pList;
- X while (!null(pXFinger) && iErr == VEOS_SUCCESS) {
- X
- X
- X /** make room for another grouple element **/
- X
- X Nancy_NewElementsInGrouple(pGrouple, iElt, 1, GR_unspecified, 0);
- X
- X
- X /** do actual element conversion **/
- X
- X iErr = Native_XEltToVElt(car(pXFinger), &pGrouple->pEltList[iElt]);
- X
- X
- X /** advance element refs **/
- X
- X iElt ++;
- X pXFinger = cdr(pXFinger);
- X
- X } /* while */
- X
- X
- X if (iErr == VEOS_SUCCESS)
- X *hGrouple = pGrouple;
- X else
- X Nancy_DisposeGrouple(pGrouple);
- X
- X
- X return(iErr);
- X
- X } /* Native_ListToGrouple */
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************/
- XTVeosErr Native_VectToGrouple(pVect, hGrouple)
- X LVAL pVect;
- X THGrouple hGrouple;
- X{
- X TVeosErr iErr;
- X int iElts, iEltIndex;
- X TPGrouple pGrouple;
- X TPElt pVElt;
- X
- X *hGrouple = nil;
- X
- X iErr = Nancy_NewGrouple(&pGrouple);
- X
- X
- X iElts = getsz(pVect);
- X if (iElts > 0 && iErr == VEOS_SUCCESS) {
- X
- X /** make enough room for all impending elements **/
- X
- X iErr = Nancy_NewElementsInGrouple(pGrouple, 0, iElts, GR_unspecified, 0);
- X
- X
- X
- X /** convert each lisp sub-element **/
- X
- X iEltIndex = 0; pVElt = pGrouple->pEltList;
- X while (iEltIndex < iElts && iErr == VEOS_SUCCESS) {
- X
- X iErr = Native_XEltToVElt(getelement(pVect, iEltIndex), pVElt);
- X
- X iEltIndex ++; pVElt ++;
- X }
- X }
- X
- X if (iErr == VEOS_SUCCESS)
- X *hGrouple = pGrouple;
- X else
- X Nancy_DisposeGrouple(pGrouple);
- X
- X
- X return(iErr);
- X
- X } /* Native_VectToGrouple */
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************/
- XTVeosErr Native_VEltToXElt(pVElt, hXElt)
- X TPElt pVElt;
- X LVAL *hXElt;
- X{
- X TVeosErr iErr;
- X
- X
- X *hXElt = NIL;
- X
- X iErr = VEOS_SUCCESS;
- X
- X switch (pVElt->iType) {
- X
- X case GR_grouple:
- X iErr = Native_GroupleToList(pVElt->u.pGr, hXElt);
- X break;
- X
- X case GR_vector:
- X iErr = Native_GroupleToVect(pVElt->u.pGr, hXElt);
- X break;
- X
- X case GR_int:
- X *hXElt = cvfixnum(pVElt->u.iVal);
- X break;
- X
- X case GR_float:
- X *hXElt = cvflonum(pVElt->u.fVal);
- X break;
- X
- X case GR_string:
- X *hXElt = cvstring(pVElt->u.pS);
- X break;
- X
- X case GR_prim:
- X *hXElt = xlenter(pVElt->u.pS);
- X break;
- X
- X case GR_unspecified:
- X iErr = NATIVE_EMPTYELT;
- X break;
- X
- X default:
- X iErr = NATIVE_BADXTYPE;
- X break;
- X
- X }
- X
- X return(iErr);
- X
- X } /* Native_VEltToXElt */
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************/
- XTVeosErr Native_GroupleToList(pGrouple, hList)
- X TPGrouple pGrouple;
- X LVAL *hList;
- X{
- X TVeosErr iErr;
- X LVAL pNewXElt, pList;
- X int iElts, iElt;
- X
- X xlstkcheck(2);
- X xlsave(pNewXElt);
- X xlsave(pList);
- X
- X iErr = VEOS_SUCCESS;
- X iElts = pGrouple->iElts;
- X iElt = iElts - 1;
- X
- X while (iElt >= 0 && iErr == VEOS_SUCCESS) {
- X
- X iErr = Native_VEltToXElt(&pGrouple->pEltList[iElt], &pNewXElt);
- X if (iErr == VEOS_SUCCESS)
- X pList = cons(pNewXElt, pList);
- X
- X iElt --;
- X }
- X
- X *hList = pList;
- X
- X xlpopn(2);
- X
- X return(iErr);
- X
- X } /* Native_GroupleToList */
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************/
- XTVeosErr Native_GroupleToVect(pGrouple, hVect)
- X TPGrouple pGrouple;
- X LVAL *hVect;
- X{
- X TVeosErr iErr;
- X LVAL pNewXElt, pVect;
- X int iElts, iElt;
- X
- X xlstkcheck(2);
- X xlsave(pVect);
- X xlsave(pNewXElt);
- X
- X iErr = VEOS_SUCCESS;
- X iElts = pGrouple->iElts;
- X iElt = 0;
- X
- X pVect = newvector(iElts);
- X
- X while (iElt < iElts && iErr == VEOS_SUCCESS) {
- X
- X iErr = Native_VEltToXElt(&pGrouple->pEltList[iElt], &pNewXElt);
- X if (iErr == VEOS_SUCCESS)
- X setelement(pVect, iElt, pNewXElt);
- X
- X iElt ++;
- X }
- X
- X *hVect = pVect;
- X
- X xlpopn(2);
- X
- X return(iErr);
- X
- X } /* Native_GroupleToVect */
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************
- X Timestamped Xlisp <--> Nancy Conversion
- X ****************************************************************************************/
- X
- X/****************************************************************************************/
- XTVeosErr Native_NewVEltToXElt(pVElt, hXElt, time)
- X TPElt pVElt;
- X LVAL *hXElt;
- X TTimeStamp time;
- X{
- X TVeosErr iErr;
- X
- X *hXElt = NIL;
- X iErr = NATIVE_STALE;
- X
- X if (TIME_LESS_THAN(pVElt->tLastMod, time)) {
- X
- X /** old data, retrieve only contents of containers
- X **/
- X if (pVElt->iType == GR_grouple)
- X iErr = Native_NewGroupleToList(pVElt->u.pGr, hXElt, time);
- X
- X else if (pVElt->iType == GR_vector)
- X iErr = Native_NewGroupleToVect(pVElt->u.pGr, hXElt, time);
- X }
- X
- X else {
- X /** new data, retrieve completely **/
- X
- X switch (pVElt->iType) {
- X
- X case GR_grouple:
- X iErr = Native_GroupleToList(pVElt->u.pGr, hXElt);
- X break;
- X
- X case GR_vector:
- X iErr = Native_GroupleToVect(pVElt->u.pGr, hXElt);
- X break;
- X
- X case GR_int:
- X *hXElt = cvfixnum(pVElt->u.iVal);
- X iErr = VEOS_SUCCESS;
- X break;
- X
- X case GR_float:
- X *hXElt = cvflonum(pVElt->u.fVal);
- X iErr = VEOS_SUCCESS;
- X break;
- X
- X case GR_string:
- X *hXElt = cvstring(pVElt->u.pS);
- X iErr = VEOS_SUCCESS;
- X break;
- X
- X case GR_prim:
- X *hXElt = xlenter(pVElt->u.pS);
- X iErr = VEOS_SUCCESS;
- X break;
- X
- X case GR_unspecified:
- X iErr = NATIVE_EMPTYELT;
- X break;
- X
- X default:
- X iErr = NATIVE_BADXTYPE;
- X break;
- X
- X }
- X }
- X
- X return(iErr);
- X
- X } /* Native_NewVEltToXElt */
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************/
- XTVeosErr Native_NewGroupleToList(pGrouple, hList, time)
- X TPGrouple pGrouple;
- X LVAL *hList;
- X TTimeStamp time;
- X{
- X TVeosErr iErr = VEOS_SUCCESS;
- X LVAL pNewXElt, pList;
- X int iElts, iElt;
- X TPElt pVElt;
- X boolean bStale = TRUE;
- X
- X xlsave1(pNewXElt);
- X xlsave1(pList);
- X
- X iElts = pGrouple->iElts;
- X iElt = iElts - 1;
- X
- X while (iElt >= 0) {
- X
- X /** determine if caller has already seen this data **/
- X
- X iErr = Native_NewVEltToXElt(&pGrouple->pEltList[iElt], &pNewXElt, time);
- X if (iErr == VEOS_SUCCESS) {
- X /** assume caller has locked this ptr **/
- X
- X pList = cons(pNewXElt, pList);
- X bStale = FALSE;
- X }
- X
- X else if (iErr == NATIVE_STALE)
- X iErr = VEOS_SUCCESS;
- X
- X else
- X break;
- X
- X iElt --;
- X }
- X
- X if (iErr == VEOS_SUCCESS) {
- X if (bStale)
- X iErr = NATIVE_STALE;
- X
- X *hList = pList;
- X }
- X
- X xlpopn(2);
- X
- X return(iErr);
- X
- X } /* Native_NewGroupleToList */
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************/
- XTVeosErr Native_NewGroupleToVect(pGrouple, hVect, time)
- X TPGrouple pGrouple;
- X LVAL *hVect;
- X TTimeStamp time;
- X{
- X TVeosErr iErr = VEOS_SUCCESS;
- X LVAL pNewXElt, pVect;
- X int iElts, iElt;
- X boolean bStale = TRUE;
- X
- X xlsave1(pNewXElt);
- X xlsave1(pVect);
- X
- X iElts = pGrouple->iElts;
- X pVect = newvector(iElts);
- X
- X iElt = 0;
- X
- X while (iElt < iElts) {
- X
- X iErr = Native_NewVEltToXElt(&pGrouple->pEltList[iElt], &pNewXElt, time);
- X if (iErr == VEOS_SUCCESS) {
- X
- X /** assume caller has locked this ptr **/
- X
- X setelement(pVect, iElt, pNewXElt);
- X bStale = FALSE;
- X }
- X
- X else if (iErr == NATIVE_STALE)
- X iErr = VEOS_SUCCESS;
- X
- X else
- X break;
- X
- X iElt ++;
- X }
- X
- X if (iErr == VEOS_SUCCESS) {
- X if (bStale)
- X iErr = NATIVE_STALE;
- X
- X *hVect = pVect;
- X }
- X
- X xlpopn(2);
- X
- X return(iErr);
- X
- X } /* Native_NewGroupleToVect */
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************/
- XTVeosErr Native_XEltToNewVElt(pXElt, pVElt, time)
- X LVAL pXElt;
- X TPElt pVElt;
- X TTimeStamp time;
- X{
- X TVeosErr iErr;
- X
- X iErr = VEOS_SUCCESS;
- X
- X
- X /** NIL is the empty grouple **/
- X
- X if (null(pXElt)) {
- X pVElt->iType = GR_grouple;
- X iErr = Nancy_NewGrouple(&pVElt->u.pGr);
- X }
- X
- X /** case-wise conversion to nancy format **/
- X
- X else {
- X switch (ntype(pXElt)) {
- X
- X case CONS:
- X /** a list becomes a grouple **/
- X iErr = Native_ListToNewGrouple(pXElt, &pVElt->u.pGr, time);
- X pVElt->iType = GR_grouple;
- X break;
- X
- X case VECTOR:
- X /** a vector becomes a special grouple **/
- X iErr = Native_VectToNewGrouple(pXElt, &pVElt->u.pGr, time);
- X pVElt->iType = GR_vector;
- X break;
- X
- X case FIXNUM:
- X pVElt->iType = GR_int;
- X pVElt->u.iVal = getfixnum(pXElt);
- X break;
- X
- X case FLONUM:
- X pVElt->iType = GR_float;
- X pVElt->u.fVal = (float) getflonum(pXElt);
- X break;
- X
- X case STRING:
- X pVElt->iType = GR_string;
- X pVElt->u.pS = strdup((char *) getstring(pXElt));
- X break;
- X
- X case SYMBOL:
- X pVElt->iType = GR_prim;
- X pVElt->u.pS = strdup(getstring(getpname(pXElt)));
- X break;
- X
- X default:
- X iErr = NATIVE_BADVTYPE;
- X break;
- X
- X }
- X }
- X
- X pVElt->tLastMod = time;
- X
- X return(iErr);
- X
- X } /* Native_XEltToNewVElt */
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************/
- XTVeosErr Native_ListToNewGrouple(pList, hGrouple, time)
- X LVAL pList;
- X THGrouple hGrouple;
- X TTimeStamp time;
- X{
- X TVeosErr iErr;
- X LVAL pXFinger;
- X int iElt;
- X TPGrouple pGrouple;
- X TPElt pVFinger;
- X
- X xlsave1(pXFinger);
- X
- X *hGrouple = nil;
- X
- X iErr = Nancy_NewGrouple(&pGrouple);
- X iElt = 0;
- X
- X
- X /** convert each lisp sub-element **/
- X
- X pXFinger = pList;
- X while (!null(pXFinger) && iErr == VEOS_SUCCESS) {
- X
- X
- X /** make room for another grouple element **/
- X
- X Nancy_NewElementsInGrouple(pGrouple, iElt, 1, GR_unspecified, 0);
- X
- X
- X /** do actual element conversion **/
- X
- X iErr = Native_XEltToNewVElt(car(pXFinger), &pGrouple->pEltList[iElt], time);
- X
- X
- X /** advance element refs **/
- X
- X iElt ++;
- X pXFinger = cdr(pXFinger);
- X
- X } /* while */
- X
- X
- X if (iErr == VEOS_SUCCESS)
- X *hGrouple = pGrouple;
- X else
- X Nancy_DisposeGrouple(pGrouple);
- X
- X xlpop();
- X
- X return(iErr);
- X
- X } /* Native_ListToNewGrouple */
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************/
- XTVeosErr Native_VectToNewGrouple(pVect, hGrouple, time)
- X LVAL pVect;
- X THGrouple hGrouple;
- X TTimeStamp time;
- X{
- X TVeosErr iErr;
- X int iElts, iEltIndex;
- X TPGrouple pGrouple;
- X
- X
- X *hGrouple = nil;
- X
- X iErr = Nancy_NewGrouple(&pGrouple);
- X
- X
- X iElts = getsz(pVect);
- X if (iElts > 0 && iErr == VEOS_SUCCESS) {
- X
- X /** make enough room for all impending elements **/
- X
- X iErr = Nancy_NewElementsInGrouple(pGrouple, 0, iElts, GR_unspecified, 0);
- X
- X
- X
- X /** convert each lisp sub-element **/
- X
- X iEltIndex = 0;
- X while (iEltIndex < iElts && iErr == VEOS_SUCCESS) {
- X
- X iErr = Native_XEltToNewVElt(getelement(pVect, iEltIndex),
- X &pGrouple->pEltList[iEltIndex], time);
- X iEltIndex ++;
- X }
- X }
- X
- X if (iErr == VEOS_SUCCESS)
- X *hGrouple = pGrouple;
- X else
- X Nancy_DisposeGrouple(pGrouple);
- X
- X
- X return(iErr);
- X
- X } /* Native_VectToNewGrouple */
- X/****************************************************************************************/
- X
- X
- X/****************************************************************************************
- X Pattern Xlisp <--> Nancy Conversion
- X ****************************************************************************************/
- X
- X
- X/****************************************************************************************/
- XTVeosErr Native_GetPatternArg(hPattern, iMatchFlag)
- X THGrouple hPattern;
- X int iMatchFlag;
- X{
- X LVAL pXElt;
- X TVeosErr iErr;
- X
- X
- X SUBST = FALSE;
- X VOID = FALSE;
- X MOD = (iMatchFlag == NANCY_ReplaceMatch);
- X
- X
- X /** get lisp pattern list **/
- X
- X pXElt = xlgalist();
- X
- X
- X /** dispatch lisp->veos conversion **/
- X
- X iErr = Native_PatListToGrouple(pXElt, hPattern);
- X
- X#ifndef OPTIMAL
- X if (iErr == VEOS_SUCCESS) {
- X if (iMatchFlag == NANCY_ReplaceMatch) {
- X if (!SUBST && !VOID)
- X iErr = NATIVE_NOREPLACEMARK;
- X }
- X else {
- X if (VOID)
- X iErr = NATIVE_NOVOID;
- X else if (!SUBST)
- X iErr = NATIVE_NOFETCHMARK;
- X }
- X }
- X#endif
- X
- X return(iErr);
- X
- X } /* Native_GetPatternArg */
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************/
- XTVeosErr Native_PatXEltToVElt(pXElt, pVElt)
- X LVAL pXElt;
- X TPElt pVElt;
- X{
- X TVeosErr iErr;
- X
- X iErr = VEOS_SUCCESS;
- X
- X
- X /** NIL is the empty grouple **/
- X
- X if (null(pXElt)) {
- X iErr = Nancy_NewGrouple(&pVElt->u.pGr);
- X pVElt->iType = GR_grouple;
- X }
- X
- X
- X /** case-wise conversion to nancy format **/
- X
- X else {
- X switch (ntype(pXElt)) {
- X
- X case CONS:
- X /** a list becomes a grouple **/
- X iErr = Native_PatListToGrouple(pXElt, &pVElt->u.pGr);
- X pVElt->iType = GR_grouple;
- X break;
- X
- X case VECTOR:
- X /** a vector becomes a special grouple **/
- X iErr = Native_PatVectToGrouple(pXElt, &pVElt->u.pGr);
- X pVElt->iType = GR_vector;
- X break;
- X
- X case FIXNUM:
- X pVElt->iType = GR_int;
- X pVElt->u.iVal = getfixnum(pXElt);
- X break;
- X
- X case FLONUM:
- X pVElt->iType = GR_float;
- X pVElt->u.fVal = (float) getflonum(pXElt);
- X break;
- X
- X case STRING:
- X pVElt->iType = GR_string;
- X pVElt->u.pS = strdup((char *) getstring(pXElt));
- X break;
- X
- X case SYMBOL:
- X iErr = Native_ConvertSymbol(pXElt, pVElt);
- X break;
- X
- X default:
- X iErr = NATIVE_BADVTYPE;
- X break;
- X }
- X }
- X
- X return(iErr);
- X
- X } /* Native_PatXEltToVElt */
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************/
- XTVeosErr Native_PatListToGrouple(pList, hGrouple)
- X LVAL pList;
- X THGrouple hGrouple;
- X{
- X TVeosErr iErr;
- X LVAL pXFinger;
- X int iElt;
- X TPGrouple pGrouple;
- X TPElt pVFinger;
- X TPatStatRec patPB;
- X TElt eltNew;
- X
- X
- X /******************
- X ** setup locals **
- X ******************/
- X
- X *hGrouple = nil;
- X iErr = Nancy_NewGrouple(&pGrouple);
- X
- X /** by default, a grouple is literally an ordered list of elements.
- X ** in some cases, a pattern grouple can specifiy an order-blind element
- X ** collection. in other words, a content-dependent-pattern.
- X **/
- X patPB.bOrdered = TRUE;
- X
- X /** prepare to check for pattern format inconsistencies **/
- X
- X patPB.bExpContent = FALSE;
- X patPB.bExpOrder = FALSE;
- X patPB.bMarkedWithin = FALSE;
- X patPB.bTouchedWithin = FALSE;
- X
- X patPB.bMarkNextElt = FALSE;
- X patPB.bTouchNextElt = FALSE;
- X patPB.bMustEnd = FALSE;
- X patPB.bGetAnother = FALSE;
- X
- X
- X /***********************************
- X ** convert each lisp sub-element **
- X ***********************************/
- X
- X pXFinger = pList;
- X while (!null(pXFinger)) {
- X
- X eltNew = NIL_ELT;
- X
- X /** do actual element conversion **/
- X
- X iErr = Native_PatXEltToVElt(car(pXFinger), &eltNew);
- X if (iErr != VEOS_SUCCESS)
- X break;
- X
- X iErr = Native_PatVEltClerical(&eltNew, &patPB);
- X if (iErr != VEOS_SUCCESS)
- X break;
- X
- X if (patPB.bGetAnother) {
- X
- X /** this elt was actually a modifier elt for next one.
- X ** prepare for caller forgetting to pass next elt
- X **/
- X iErr = NATIVE_NOTEND;
- X }
- X
- X else {
- X /** place converted nancy element into dest grouple **/
- X
- X Nancy_NewElementsInGrouple(pGrouple, pGrouple->iElts,
- X 1, GR_unspecified, 0);
- X pGrouple->pEltList[pGrouple->iElts - 1] = eltNew;
- X }
- X
- X
- X /** advance element refs **/
- X
- X pXFinger = cdr(pXFinger);
- X } /* while */
- X
- X if (iErr != VEOS_SUCCESS)
- X Nancy_DisposeGrouple(pGrouple);
- X
- X else {
- X if (!patPB.bOrdered)
- X SETFLAG(NANCY_ContentMask, pGrouple->iFlags);
- X if (patPB.bMarkedWithin)
- X SETFLAG(NANCY_MarkWithinMask, pGrouple->iFlags);
- X if (patPB.bTouchedWithin)
- X SETFLAG(NANCY_TouchWithinMask, pGrouple->iFlags);
- X
- X *hGrouple = pGrouple;
- X }
- X
- X return(iErr);
- X
- X } /* Native_PatListToGrouple */
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************/
- XTVeosErr Native_PatVectToGrouple(pVect, hGrouple)
- X LVAL pVect;
- X THGrouple hGrouple;
- X{
- X TVeosErr iErr;
- X LVAL pXFinger;
- X int iXElts, iXEltIndex;
- X TPGrouple pGrouple;
- X TPatStatRec patPB;
- X TElt eltNew;
- X
- X /******************
- X ** setup locals **
- X ******************/
- X
- X *hGrouple = nil;
- X iErr = Nancy_NewGrouple(&pGrouple);
- X
- X /** by default, a grouple is literally an ordered list of elements.
- X ** in some cases, a pattern grouple can specifiy an order-blind element
- X ** collection. in other words, a content-dependent-pattern.
- X **/
- X patPB.bOrdered = TRUE;
- X
- X /** prepare to check for pattern format inconsistencies **/
- X
- X patPB.bExpContent = FALSE;
- X patPB.bExpOrder = FALSE;
- X patPB.bMarkedWithin = FALSE;
- X patPB.bTouchedWithin = FALSE;
- X
- X patPB.bMarkNextElt = FALSE;
- X patPB.bTouchNextElt = FALSE;
- X patPB.bMustEnd = FALSE;
- X patPB.bGetAnother = FALSE;
- X
- X iXElts = getsz(pVect);
- X if (iXElts > 0 && iErr == VEOS_SUCCESS) {
- X
- X /***********************************
- X ** convert each lisp sub-element **
- X ***********************************/
- X
- X iXEltIndex = 0;
- X while (iXEltIndex < iXElts) {
- X
- X
- X /** cache current vector element **/
- X
- X pXFinger = getelement(pVect, iXEltIndex);
- X eltNew = NIL_ELT;
- X
- X /** do actual element conversion **/
- X
- X iErr = Native_PatXEltToVElt(pXFinger, &eltNew);
- X if (iErr != VEOS_SUCCESS)
- X break;
- X
- X iErr = Native_PatVEltClerical(&eltNew, &patPB);
- X if (iErr != VEOS_SUCCESS)
- X break;
- X
- X if (patPB.bGetAnother) {
- X
- X /** this elt was actually a modifier elt for next one.
- X ** prepare for caller forgetting to pass next elt
- X **/
- X iErr = NATIVE_NOTEND;
- X }
- X
- X else {
- X /** place converted nancy element into dest grouple **/
- X
- X Nancy_NewElementsInGrouple(pGrouple, pGrouple->iElts,
- X 1, GR_unspecified, 0);
- X pGrouple->pEltList[pGrouple->iElts - 1] = eltNew;
- X }
- X
- X
- X /** advance element refs **/
- X
- X iXEltIndex ++;
- X
- X } /* while */
- X }
- X
- X if (iErr != VEOS_SUCCESS)
- X Nancy_DisposeGrouple(pGrouple);
- X
- X else {
- X if (!patPB.bOrdered)
- X SETFLAG(NANCY_ContentMask, pGrouple->iFlags);
- X if (patPB.bMarkedWithin)
- X SETFLAG(NANCY_MarkWithinMask, pGrouple->iFlags);
- X if (patPB.bTouchedWithin)
- X SETFLAG(NANCY_TouchWithinMask, pGrouple->iFlags);
- X
- X *hGrouple = pGrouple;
- X }
- X
- X return(iErr);
- X
- X } /* Native_PatVectToGrouple */
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************/
- XTVeosErr Native_PatVEltClerical(pVElt, pStats)
- X TPElt pVElt;
- X TPPatStatRec pStats;
- X{
- X TVeosErr iErr = VEOS_SUCCESS;
- X
- X#ifndef OPTIMAL
- X if (pStats->bMustEnd)
- X iErr = NATIVE_NOTEND;
- X
- X else {
- X /** catch possible undefined expressions **/
- X
- X switch (pVElt->iType) {
- X
- X case GR_these:
- X if (pStats->bExpContent)
- X iErr = NATIVE_CANTMIX;
- X break;
- X
- X case GR_theseall:
- X if (pStats->bExpContent)
- X iErr = NATIVE_CANTMIX;
- X break;
- X
- X case GR_some:
- X iErr = NATIVE_NOSTARN;
- X break;
- X
- X case GR_any:
- X if (pStats->bExpOrder)
- X iErr = NATIVE_CANTMIX;
- X break;
- X
- X case GR_here:
- X if (SUBST || VOID)
- X iErr = NATIVE_TOOMANYMARKS;
- X else if (pStats->bGetAnother)
- X iErr = NATIVE_MODVOID;
- X break;
- X
- X case GR_mark:
- X if (SUBST || VOID)
- X iErr = NATIVE_TOOMANYMARKS;
- X else if (pStats->bGetAnother)
- X iErr = NATIVE_THISWHAT;
- X break;
- X
- X case GR_touch:
- X if (!MOD)
- X iErr = NATIVE_NOTOUCH;
- X else if (pStats->bGetAnother)
- X iErr = NATIVE_THISWHAT;
- X break;
- X
- X default:
- X break;
- X } /* switch */
- X }
- X#endif
- X
- X if (iErr == VEOS_SUCCESS) {
- X
- X /** mark the element for nancy matcher **/
- X
- X if (pStats->bMarkNextElt) {
- X SETFLAG(NANCY_EltMarkMask, pVElt->iFlags);
- X pStats->bMarkNextElt = FALSE;
- X pStats->bGetAnother = FALSE;
- X }
- X
- X if (pStats->bTouchNextElt) {
- X SETFLAG(NANCY_EltTouchMask, pVElt->iFlags);
- X pStats->bTouchNextElt = FALSE;
- X pStats->bGetAnother = FALSE;
- X }
- X
- X
- X switch (pVElt->iType) {
- X
- X case GR_these:
- X pStats->bExpOrder = TRUE;
- X break;
- X
- X case GR_any:
- X pStats->bOrdered = FALSE;
- X pStats->bExpContent = TRUE;
- X pStats->bMustEnd = TRUE;
- X break;
- X
- X case GR_theseall:
- X pStats->bExpOrder = TRUE;
- X pStats->bMustEnd = TRUE;
- X break;
- X
- X case GR_here:
- X VOID = TRUE;
- X SETFLAG(NANCY_EltMarkMask, pVElt->iFlags);
- X pStats->bMarkedWithin = TRUE;
- X break;
- X
- X case GR_mark:
- X SUBST = TRUE;
- X pStats->bMarkedWithin = TRUE;
- X pStats->bMarkNextElt = TRUE;
- X pStats->bGetAnother = TRUE;
- X break;
- X
- X case GR_touch:
- X pStats->bTouchedWithin = TRUE;
- X pStats->bTouchNextElt = TRUE;
- X pStats->bGetAnother = TRUE;
- X break;
- X
- X default:
- X break;
- X } /* switch */
- X }
- X
- X return(iErr);
- X
- X } /* Native_PatVEltClerical */
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************/
- XTVeosErr Native_ConvertSymbol(pXElt, pVElt)
- X LVAL pXElt;
- X TPElt pVElt;
- X{
- X TVeosErr iErr = VEOS_SUCCESS;
- X char *sSrc;
- X boolean bParsed = FALSE;
- X
- X
- X sSrc = (char *) getstring(getpname(pXElt));
- X
- X switch(sSrc[0]) {
- X
- X
- X case '^': /* '^' marks the void for insertion */
- X if (sSrc[1] == '\0') {
- X pVElt->iType = GR_here;
- X bParsed = TRUE;
- X }
- X break;
- X
- X case '>': /* '>' is a mark for the next element */
- X if (sSrc[1] == '\0') {
- X pVElt->iType = GR_mark;
- X bParsed = TRUE;
- X }
- X break;
- X
- X case '~': /* '~' touches the next element */
- X if (sSrc[1] == '\0') {
- X pVElt->iType = GR_touch;
- X bParsed = TRUE;
- X }
- X break;
- X
- X case '@': /* '@' is wildcard for ordered elements **/
- X
- X /** special form (@) means exactly one element **/
- X if (sSrc[1] == '\0') {
- X pVElt->iType = GR_these;
- X pVElt->u.iVal = 1;
- X bParsed = TRUE;
- X }
- X
- X /** special form (@n) means exactly n elts **/
- X else if (IsIntStr(&sSrc[1]) == VEOS_SUCCESS) {
- X if ((pVElt->u.iVal = atoi(&sSrc[1])) < 1)
- X iErr = NATIVE_CRAZYWILD;
- X else
- X pVElt->iType = GR_these;
- X bParsed = TRUE;
- X }
- X
- X /** special form (@@) means zero or more elts **/
- X else if (sSrc[1] == '@' && sSrc[2] == '\0') {
- X pVElt->iType = GR_theseall;
- X bParsed = TRUE;
- X }
- X break;
- X
- X
- X case '*': /* '*' is wildcard for unordered elements */
- X
- X /** special form (*) means exatly one element **/
- X if (sSrc[1] == '\0') {
- X pVElt->iType = GR_some;
- X pVElt->u.iVal = 1;
- X bParsed = TRUE;
- X }
- X
- X /** special form (*n) means exactly n elts **/
- X else if (IsIntStr(&sSrc[1]) == VEOS_SUCCESS) {
- X if ((pVElt->u.iVal = atoi(&sSrc[1])) < 1)
- X iErr = NATIVE_CRAZYWILD;
- X else
- X pVElt->iType = GR_some;
- X bParsed = TRUE;
- X }
- X
- X /** special form (**) means zero or more elts **/
- X else if (sSrc[1] == '*' && sSrc[2] == '\0') {
- X pVElt->iType = GR_any;
- X bParsed = TRUE;
- X }
- X break;
- X
- X } /* switch */
- X
- X
- X /** save symbol's name as veos prim type **/
- X
- X if (!bParsed && iErr == VEOS_SUCCESS) {
- X pVElt->iType = GR_prim;
- X pVElt->u.pS = strdup(sSrc);
- X }
- X
- X
- X return(iErr);
- X
- X } /* Native_ConvertSymbol */
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************
- X Xlisp <--> Linearized Data Conversion
- X ****************************************************************************************/
- X
- X
- X/****************************************************************************************/
- XTVeosErr Native_XEltToMsgRec(pXData, pMsgRec)
- X LVAL pXData;
- X TPMsgRec pMsgRec;
- X{
- X TVeosErr iErr;
- X
- X pMsgRec->iLen = 0;
- X pMsgRec->sMessage = TALK_BUFFER;
- X
- X
- X /** perform data conversion to flat network-friendly form **/
- X
- X iErr = Native_XEltToMessage(pXData, pMsgRec->sMessage, &pMsgRec->iLen);
- X
- X if (iErr != VEOS_SUCCESS)
- X Native_TrapErr(iErr, pXData);
- X
- X
- X return(iErr);
- X
- X } /* Native_XEltToMsgRec */
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************/
- XTVeosErr Native_XEltToMessage(pXElt, pBuffer, pLen)
- X LVAL pXElt;
- X char *pBuffer;
- X int *pLen;
- X{
- X TVeosErr iErr;
- X int iLen;
- X TF2L fTrans;
- X
- X iErr = VEOS_SUCCESS;
- X
- X /** message element is: element type, then data (except for NIL)
- X ** assume pBuffer is aligned
- X **/
- X
- X if (null(pXElt)) {
- X
- X /** nil element is empty grouple **/
- X *(int *) pBuffer = htonl(GR_grouple);
- X pBuffer += 4;
- X
- X /** empty grouple has zero elements **/
- X *(int *) pBuffer = htonl(0);
- X
- X iLen = 8;
- X }
- X else {
- X
- X switch (ntype(pXElt)) {
- X
- X case CONS:
- X *(int *) pBuffer = htonl(GR_grouple);
- X pBuffer += 4;
- X iLen = 4;
- X iErr = Native_ListToMessage(pXElt, pBuffer, &iLen);
- X break;
- X
- X case VECTOR:
- X *(int *) pBuffer = htonl(GR_vector);
- X pBuffer += 4;
- X iLen = 4;
- X iErr = Native_VectToMessage(pXElt, pBuffer, &iLen);
- X break;
- X
- X case FIXNUM:
- X *(int *) pBuffer = htonl(GR_int);
- X pBuffer += 4;
- X *(long *) pBuffer = htonl(getfixnum(pXElt));
- X iLen = 8;
- X break;
- X
- X case FLONUM:
- X *(int *) pBuffer = htonl(GR_float);
- X pBuffer += 4;
- X fTrans.u.f = getflonum(pXElt);
- X *(long *) pBuffer = htonl(fTrans.u.l);
- X iLen = 8;
- X break;
- X
- X case STRING:
- X *(int *) pBuffer = htonl(GR_string);
- X pBuffer += 4;
- X strcpy(pBuffer, getstring(pXElt));
- X iLen = 4 + MEMSIZE(strlen(getstring(pXElt)) + 1);
- X break;
- X
- X case SYMBOL:
- X *(int *) pBuffer = htonl(GR_prim);
- X pBuffer += 4;
- X strcpy(pBuffer, getstring(getpname(pXElt)));
- X iLen = 4 + MEMSIZE(strlen(getstring(getpname(pXElt))) + 1);
- X break;
- X
- X default:
- X iErr = NATIVE_BADVTYPE;
- X iLen = 0;
- X break;
- X
- X } /* switch */
- X }
- X
- X *pLen += iLen;
- X
- X return(iErr);
- X
- X } /* Native_XEltToMessage */
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************/
- XTVeosErr Native_ListToMessage(pList, pBuffer, pLen)
- X LVAL pList;
- X char *pBuffer;
- X int *pLen;
- X{
- X TVeosErr iErr = VEOS_SUCCESS;
- X LVAL pXFinger;
- X int iLen, iElts = 0;
- X char *pListHead;
- X
- X
- X /** first code of protocol is number of elements, write later **/
- X
- X pListHead = pBuffer;
- X pBuffer = pListHead + 4;
- X *pLen += 4;
- X
- X
- X /** convert each lisp sub-element **/
- X
- X pXFinger = pList;
- X while (!null(pXFinger)) {
- X
- X /** invoke recursive translation **/
- X
- X iLen = 0;
- X iErr = Native_XEltToMessage(car(pXFinger), pBuffer, &iLen);
- X
- X if (iErr != VEOS_SUCCESS)
- X break;
- X
- X else {
- X iElts ++;
- X
- X pBuffer += iLen;
- X *pLen += iLen;
- X }
- X
- X /** advance element ref **/
- X
- X pXFinger = cdr(pXFinger);
- X
- X } /* while */
- X
- X
- X /** write number of elements **/
- X
- X *(int *) pListHead = htonl(iElts);
- X
- X return(iErr);
- X
- X } /* Native_ListToMessage */
- X/****************************************************************************************/
- X
- X
- X
- X
- X/****************************************************************************************/
- XTVeosErr Native_VectToMessage(pVect, pBuffer, pLen)
- X LVAL pVect;
- X char *pBuffer;
- X int *pLen;
- X{
- X TVeosErr iErr = VEOS_SUCCESS;
- X LVAL pXFinger;
- X int iLen, iEltIndex, iElts;
- X
- X iElts = getsz(pVect);
- X
- X /** first code of protocol is number of elements **/
- X *(int *) pBuffer = htonl(iElts);
- X
- X pBuffer += 4;
- X *pLen += 4;
- X
- X
- X /** convert each lisp sub-element **/
- X
- X iEltIndex = 0;
- X while(iEltIndex < iElts) {
- X
- X
- X /** invoke recursive translation **/
- X
- X iLen = 0;
- X iErr = Native_XEltToMessage(getelement(pVect, iEltIndex), pBuffer, &iLen);
- X
- X if (iErr != VEOS_SUCCESS)
- X break;
- X
- X else {
- X pBuffer += iLen;
- X *pLen += iLen;
- X }
- X
- X
- X /** advance element ref **/
- X
- X iEltIndex ++;
- X
- X } /* while */
- X
- X
- X return(iErr);
- X
- X } /* Native_VectToMessage */
- X/****************************************************************************************/
- X
- X
- X
- X
- X/****************************************************************************************/
- XTVeosErr Native_MessageToXElt(pBuffer, hXElt, pLen)
- X char *pBuffer;
- X LVAL *hXElt;
- X int *pLen;
- X{
- X TVeosErr iErr = VEOS_SUCCESS;
- X int iLen, iType;
- X TF2L fTrans;
- X
- X *hXElt = NIL;
- X
- X iType = ntohl(*(int *) pBuffer); /** assume pBuffer is aligned **/
- X
- X pBuffer += 4;
- X *pLen += 4;
- X
- X switch (iType) {
- X
- X case GR_grouple:
- X iLen = 0;
- X iErr = Native_MessageToList(pBuffer, hXElt, &iLen);
- X break;
- X
- X case GR_vector:
- X iLen = 0;
- X iErr = Native_MessageToVect(pBuffer, hXElt, &iLen);
- X break;
- X
- X case GR_int:
- X *hXElt = cvfixnum((int) ntohl(*(long *) pBuffer));
- X iLen = 4;
- X break;
- X
- X case GR_float:
- X fTrans.u.l = ntohl(*(long *) pBuffer);
- X *hXElt = cvflonum(fTrans.u.f);
- X iLen = 4;
- X break;
- X
- X case GR_string:
- X *hXElt = cvstring(pBuffer);
- X iLen = MEMSIZE(strlen(pBuffer) + 1);
- X break;
- X
- X case GR_prim:
- X *hXElt = xlenter(pBuffer);
- X iLen = MEMSIZE(strlen(pBuffer) + 1);
- X break;
- X
- X case GR_unspecified:
- X default:
- X iLen = 0;
- X break;
- X
- X } /* switch */
- X
- X *pLen += iLen;
- X
- X return(iErr);
- X
- X } /* Native_MessageToXElt */
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************/
- XTVeosErr Native_MessageToList(pBuffer, hList, pLen)
- X char *pBuffer;
- X LVAL *hList;
- X int *pLen;
- X{
- X TVeosErr iErr = VEOS_SUCCESS;
- X LVAL pXFinger;
- X int iLen, iElts, iEltIndex;
- X char *pListHead;
- X LVAL pList, pXElt;
- X
- X xlstkcheck(2);
- X xlsave(pList);
- X xlsave(pXElt);
- X
- X /** extract # of elements from first part of grouple data **/
- X
- X iElts = ntohl(*(int *) pBuffer);
- X
- X pBuffer += 4;
- X *pLen += 4;
- X
- X
- X /** convert each element one at a time, 'talk msg format' -> list' **/
- X
- X iEltIndex = 0;
- X while (iEltIndex < iElts) {
- X
- X iLen = 0;
- X
- X /** extract elt data, allocate specific elt mem, stuff it with data. **/
- X
- X iErr = Native_MessageToXElt(pBuffer, &pXElt, &iLen);
- X
- X if (iErr != VEOS_SUCCESS)
- X break;
- X
- X else {
- X pBuffer += iLen;
- X *pLen += iLen;
- X
- X pList = cons(pXElt, pList);
- X }
- X
- X iEltIndex ++;
- X }
- X
- X if (iErr == VEOS_SUCCESS) {
- X
- X *hList = ReverseList(pList);
- X }
- X
- X xlpopn(2);
- X
- X return(iErr);
- X
- X } /* Native_MessageToList */
- X/****************************************************************************************/
- X
- X
- X
- X
- X/****************************************************************************************/
- XTVeosErr Native_MessageToVect(pBuffer, hVect, pLen)
- X char *pBuffer;
- X LVAL *hVect;
- X int *pLen;
- X{
- X TVeosErr iErr = VEOS_SUCCESS;
- X int iLen, iElts, iEltIndex;
- X LVAL pVect, pXElt;
- X
- X xlstkcheck(2);
- X xlsave(pVect);
- X xlsave(pXElt);
- X
- X /** extract # of elements from first part of grouple data **/
- X
- X iElts = ntohl(*(int *) pBuffer);
- X
- X pBuffer += 4;
- X *pLen += 4;
- X
- X
- X /** create new lisp vector as container **/
- X
- X pVect = newvector(iElts);
- X
- X
- X /** convert each element one at a time **/
- X
- X iEltIndex = 0;
- X while (iEltIndex < iElts) {
- X
- X iLen = 0;
- X
- X /** extract elt data, allocate specific elt mem, stuff it with data. **/
- X
- X iErr = Native_MessageToXElt(pBuffer, &pXElt, &iLen);
- X if (iErr != VEOS_SUCCESS)
- X break;
- X
- X else {
- X pBuffer += iLen;
- X *pLen += iLen;
- X
- X setelement(pVect, iEltIndex, pXElt);
- X }
- X
- X iEltIndex ++;
- X }
- X
- X
- X if (iErr == VEOS_SUCCESS)
- X *hVect = pVect;
- X
- X xlpopn(2);
- X
- X return(iErr);
- X
- X } /* Native_MessageToVect */
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************/
- XTVeosErr Native_TrapErr(iErr, pXElt)
- X TVeosErr iErr;
- X LVAL pXElt;
- X{
- X str63 sErr;
- X
- X switch(iErr) {
- X
- X case NATIVE_BADTYPE:
- X xlbadtype(pXElt);
- X break;
- X case NATIVE_NOKERNEL:
- X xlfail("veos kernel not initialized, use (vinit <port-num>)");
- X break;
- X case NATIVE_BADFREQ:
- X xlerror("'!' expected", pXElt);
- X break;
- X case NATIVE_2KERNELS:
- X xlfail("veos kernel already initialized");
- X break;
- X case NATIVE_BADVTYPE:
- X xlerror("veos does not support that data type", pXElt == nil ? s_unbound : pXElt);
- X break;
- X case NATIVE_BADXTYPE:
- X xlerror("xlisp does not support that data type from veos",
- X pXElt == nil ? s_unbound : pXElt);
- X break;
- X case NATIVE_EMPTYELT:
- X xlerror("empty data element from veos, probably a memory error",
- X pXElt == nil ? s_unbound : pXElt);
- X break;
- X case NATIVE_NODATA:
- X xlerror("no veos data to match... only the void remains", s_unbound);
- X break;
- X case NATIVE_THISWHAT:
- X xlerror("pattern element modifier ('>' or '~') must be followed by a matchable element", pXElt == nil ? s_unbound : pXElt);
- X break;
- X case NATIVE_TOOMANYMARKS:
- X xlerror("patterns must contain exactly one '>' or '^'",
- X pXElt == nil ? s_unbound : pXElt);
- X break;
- X case NATIVE_CANTMIX:
- X xlerror("can't mix '@' and '*'", pXElt == nil ? s_unbound : pXElt);
- X break;
- X case NATIVE_NOTEND:
- X xlerror("indefinite wildcards (eg '@@' or '**') can only appear at end of grouple in pattern",
- X pXElt == nil ? s_unbound : pXElt);
- X break;
- X case NATIVE_NOREPLACEMARK:
- X xlerror("pattern must contain '>' or '^'", pXElt == nil ? s_unbound : pXElt);
- X break;
- X case NATIVE_NOFETCHMARK:
- X xlerror("pattern must contain '>'", pXElt == nil ? s_unbound : pXElt);
- X break;
- X case NATIVE_NOVOID:
- X xlerror("cannot get or copy from the void ('^')",
- X pXElt == nil ? s_unbound : pXElt);
- X break;
- X case NATIVE_BADPATSYMBOL:
- X xlerror("symbol not recognized", pXElt == nil ? s_unbound : pXElt);
- X break;
- X case NATIVE_CRAZYWILD:
- X xlerror("nonsensical number of wildcard elements",
- X pXElt == nil ? s_unbound : pXElt);
- X break;
- X case NATIVE_MATCHFAIL:
- X xlerror("match and/or replace did not succeed",
- X pXElt == nil ? s_unbound : pXElt);
- X break;
- X case NATIVE_NOSTARN:
- X xlerror("the '*n' feature is not supported",
- X pXElt == nil ? s_unbound : pXElt);
- X break;
- X case NATIVE_BADVOID:
- X xlerror("ambiguous void marker (can't use '^' in pattern grouple containing '*')",
- X pXElt == nil ? s_unbound : pXElt);
- X break;
- X case NATIVE_NOHOST:
- X xlerror("host not recognized", pXElt == nil ? s_unbound : pXElt);
- X break;
- X case NATIVE_NOTOUCH:
- X xlerror("can't touch (eg. '~') elements during nondestructive grouplespace access", pXElt == nil ? s_unbound : pXElt);
- X break;
- X case NATIVE_MODVOID:
- X xlerror("can't use element modifiers ('>' or '~') with the void ('^')", pXElt == nil ? s_unbound : pXElt);
- X break;
- X case VEOS_SUCCESS:
- X break;
- X default:
- X sprintf(sErr, "unexpected error %d", iErr);
- X xlerror(sErr, pXElt == nil ? s_unbound : pXElt);
- X break;
- X }
- X
- X return(VEOS_SUCCESS);
- X
- X } /* Native_TrapErr */
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************/
- Xboolean IsUidElt(pXElt)
- X LVAL pXElt;
- X{
- X return(vectorp(pXElt) &&
- X getsz(pXElt) == 2 &&
- X stringp(getelement(pXElt, 0)) &&
- X fixp(getelement(pXElt, 1)));
- X
- X } /* IsUidElt */
- X/****************************************************************************************/
- X
- X
- X/****************************************************************************************/
- XTVeosErr XVect2Uid(pXElt, pUid)
- X LVAL pXElt;
- X TPUid pUid;
- X{
- X TVeosErr iErr;
- X
- X /** assume sanity is checked **/
- X
- X iErr = Sock_ResolveHost(getstring(getelement(pXElt, 0)), &pUid->lHost);
- X if (iErr == VEOS_SUCCESS)
- X pUid->iPort = getfixnum(getelement(pXElt, 1));
- X else
- X iErr = NATIVE_NOHOST;
- X
- X return(iErr);
- X
- X } /* XVect2Uid */
- X/****************************************************************************************/
- X
- X
- X/****************************************************************************************/
- XTVeosErr Uid2XVect(pUid, hXElt)
- X TPUid pUid;
- X LVAL *hXElt;
- X{
- X str255 sTemp;
- X
- X /** assume sanity is checked **/
- X
- X if (Sock_IP2StrHost(pUid->lHost, sTemp) == VEOS_SUCCESS ||
- X Sock_IP2StrAddr(pUid->lHost, sTemp) == VEOS_SUCCESS) {
- X
- X /** assume caller locked *hXElt **/
- X
- X *hXElt = newvector(2);
- X setelement(*hXElt, 0, cvstring(sTemp));
- X setelement(*hXElt, 1, cvfixnum(pUid->iPort));
- X }
- X
- X return(VEOS_SUCCESS);
- X
- X } /* Uid2XVect */
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************/
- XTVeosErr Native_XVectsToUids(pList, hDests)
- X LVAL pList;
- X THUidNode hDests;
- X{
- X TVeosErr iErr = VEOS_SUCCESS;
- X TPUidNode pDests, pNode;
- X LVAL pXFinger;
- X
- X /** convert lisp 'uid' vectors to nancy uids **/
- X
- X pDests = nil;
- X pXFinger = pList;
- X while (!null(pXFinger)) {
- X
- X#ifndef OPTIMAL
- X if (!IsUidElt(car(pXFinger))) {
- X iErr = NATIVE_BADTYPE;
- X break;
- X }
- X#endif
- X iErr = Shell_NewBlock(sizeof(TUidNode), &pNode, "uid-node");
- X
- X if (iErr != VEOS_SUCCESS)
- X break;
- X
- X else{
- X /** add new node to list **/
- X
- X pNode->pNext = pDests;
- X pDests = pNode;
- X
- X
- X /** convert addr to internal format **/
- X
- X iErr = XVect2Uid(car(pXFinger), &pNode->addr);
- X }
- X
- X pXFinger = cdr(pXFinger);
- X
- X } /* while */
- X
- X if (iErr == VEOS_SUCCESS)
- X *hDests = pDests;
- X else
- X Native_DisposeUids(pDests);
- X
- X return(iErr);
- X
- X } /* Native_XVectsToUids */
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************/
- XTVeosErr Native_DisposeUids(pDests)
- X TPUidNode pDests;
- X{
- X TPUidNode pSave;
- X
- X while (pDests) {
- X
- X pSave = pDests->pNext;
- X Shell_ReturnBlock(pDests, sizeof(TUidNode), "uid-node");
- X pDests = pSave;
- X }
- X
- X return(VEOS_SUCCESS);
- X
- X } /* Native_DisposeUids */
- X/****************************************************************************************/
- X
- X
- X/****************************************************************************************/
- XTVeosErr IsIntStr(sSrc)
- X char *sSrc;
- X{
- X TVeosErr iErr;
- X
- X iErr = VEOS_FAILURE;
- X if (sSrc) {
- X
- X for (iErr = VEOS_SUCCESS;
- X sSrc[0] != '\0' && iErr == VEOS_SUCCESS;
- X sSrc ++)
- X
- X if (!isdigit(sSrc[0]))
- X iErr = VEOS_FAILURE;
- X }
- X
- X return(iErr);
- X
- X } /* IsIntStr */
- X/****************************************************************************************/
- X
- X
- END_OF_FILE
- if test 43094 -ne `wc -c <'src/kernel_current/shell/xv_glutils.c'`; then
- echo shar: \"'src/kernel_current/shell/xv_glutils.c'\" unpacked with wrong size!
- fi
- # end of 'src/kernel_current/shell/xv_glutils.c'
- fi
- echo shar: End of archive 14 \(of 16\).
- cp /dev/null ark14isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 16 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-